<template>
  <div class="app">
    <div class="overlay"></div>
    <div class="container">
      <div style="flex: 0 0 20%"></div>
      <section class="lyrics-box" ref="lyricsBox">
        <div
          class="lyrics-inner"
          :style="{ transform: `translateY(${translateY}px)`, ...cssVars }"
          ref="inner"
        >
          <div
            v-for="(line, idx) in lines"
            :key="idx"
            :class="['lyric-line', { current: idx === currentIndex }]"
            :data-idx="idx"
            ref="lineEls"
          >
            <span class="bg-text">{{ line.text }}</span>
            <span class="fg-text">{{ line.text }}</span>
          </div>
        </div>
      </section>

      <section
        class="controller-box"
        :class="{ visible: controllerVisible }"
        @mouseleave="controlsHidden"
        @mousemove="controlsShow"
      >
        <div class="controls">
          <button @click="togglePlay" class="play-btn">
            {{ playing ? "暂停" : "播放" }}
          </button>
          <div class="time">
            {{ formatTime(currentTime) }} / {{ formatTime(duration) }}
          </div>
          <div class="volume-wrap">
            <button class="mute-btn" @click="muted = !muted">
              {{ muted ? "静音" : "声音" }}
            </button>
            <input
              class="volume"
              type="range"
              min="0"
              max="1"
              step="0.01"
              v-model.number="volume"
            />
          </div>
        </div>

        <input
          class="progress"
          type="range"
          min="0"
          :max="Math.max(0, duration)"
          step="0.01"
          v-model.number="currentTime"
          @input="onSeek"
        />
      </section>
    </div>
  </div>
</template>

<script setup>
import {
  ref,
  reactive,
  onMounted,
  nextTick,
  watch,
  computed,
  onUnmounted,
} from "vue";

// 资源路径（使用相对于 src 的路径，Vite 会处理）
const audioUrl = new URL("./assets/audios/游京.mp3", import.meta.url).href;
const lrcUrl = new URL("./assets/audios/游京.lrc", import.meta.url).href;

const audio = new Audio();
audio.src = audioUrl;
audio.preload = "metadata";
audio.volume = 1;

const lines = ref([]); // {time, text}
const currentIndex = ref(0);
const playing = ref(false);
const duration = ref(0);
const currentTime = ref(0);
const volume = ref(1);
const muted = ref(false);

// 添加响应式屏幕宽度和字体大小变量
const screenWidth = ref(window.innerWidth);
const bgSize = ref(64);
const fgSize = ref(64);
const otherSize = ref(32);
const currentLineHeight = ref(120);
const otherLineHeight = ref(56);

// 计算CSS变量
const cssVars = computed(() => ({
  "--bg-size": `${bgSize.value}px`,
  "--fg-size": `${fgSize.value}px`,
  "--other-size": `${otherSize.value}px`,
  "--current-line-height": `${currentLineHeight.value}px`,
  "--other-line-height": `${otherLineHeight.value}px`,
}));

// 控制区显示/隐藏状态与计时器
const controllerVisible = ref(true);
let hideTimer = null;

const controlsShow = function () {
  // 每次鼠标移动，立即显示控制区，并重置隐藏计时器
  controllerVisible.value = true;
  if (hideTimer) {
    clearTimeout(hideTimer);
    hideTimer = null;
  }
  // 不在此处设置隐藏延时，这里只在 mouseleave 启动延时
};

const controlsHidden = function () {
  // 鼠标离开后，3秒后再隐藏（允许短暂离开不立即隐藏）
  if (hideTimer) clearTimeout(hideTimer);
  hideTimer = setTimeout(() => {
    controllerVisible.value = false;
    hideTimer = null;
  }, 1000);
};

onUnmounted(() => {
  if (hideTimer) {
    clearTimeout(hideTimer);
    hideTimer = null;
  }
});
// 根据屏幕宽度设置字体大小
function setSizesFromWidth(w) {
  if (w >= 2048) {
    // 大屏幕设备 >= 2048px
    bgSize.value = 84;
    fgSize.value = 54;
    otherSize.value = 36;
  } else if (w > 520) {
    // 平板设备或小屏幕电脑 520px < w < 2048px
    bgSize.value = 54;
    fgSize.value = 40;
    otherSize.value = 32;
  } else {
    // 移动设备 <= 520px
    bgSize.value = 28;
    fgSize.value = 25;
    otherSize.value = 24;
  }

  // 根据字体大小调整行高
  currentLineHeight.value = Math.round(
    Math.max(bgSize.value, fgSize.value) * 1.5
  );
  otherLineHeight.value = Math.round(otherSize.value * 1.5);
}

const lyricsBox = ref(null);
const inner = ref(null);
const lineEls = ref([]);
const translateY = ref(0);

function parseLRC(text) {
  const res = [];
  const lines = text.split(/\r?\n/);
  const timeReg = /\[(\d{1,2}):(\d{2})(?:\.(\d{1,3}))?\]/g;
  for (const raw of lines) {
    let m;
    const texts = raw.replace(timeReg, "").trim();
    timeReg.lastIndex = 0;
    while ((m = timeReg.exec(raw)) !== null) {
      const mm = parseInt(m[1], 10);
      const ss = parseInt(m[2], 10);
      const ms = m[3] ? parseInt((m[3] + "00").slice(0, 3), 10) : 0;
      const t = mm * 60 + ss + ms / 1000;
      res.push({ time: t, text: texts || "" });
    }
  }
  res.sort((a, b) => a.time - b.time);
  return res;
}

async function loadLrc() {
  try {
    const r = await fetch(lrcUrl);
    const txt = await r.text();
    lines.value = parseLRC(txt);
  } catch (e) {
    console.error("加载lrc失败", e);
  }
}

function updateCurrentIndex(t) {
  if (!lines.value.length) return;
  for (let i = lines.value.length - 1; i >= 0; i--) {
    if (t >= lines.value[i].time - 0.05) {
      if (currentIndex.value !== i) currentIndex.value = i;
      return;
    }
  }
  currentIndex.value = 0;
}

function formatTime(t) {
  if (!t || !isFinite(t)) return "00:00";
  const m = Math.floor(t / 60);
  const s = Math.floor(t % 60);
  return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
}

function togglePlay() {
  if (playing.value) {
    audio.pause();
  } else {
    audio.play();
  }
}

function onSeek() {
  audio.currentTime = currentTime.value;
}

// 当 audio 更新时同步状态
audio.addEventListener("timeupdate", () => {
  currentTime.value = audio.currentTime;
  updateCurrentIndex(audio.currentTime);
});
audio.addEventListener("play", () => (playing.value = true));
audio.addEventListener("pause", () => (playing.value = false));
audio.addEventListener(
  "loadedmetadata",
  () => (duration.value = audio.duration)
);

// 同步音量与静音状态
watch(volume, (v) => {
  const val = Math.max(0, Math.min(1, Number(v) || 0));
  audio.volume = val;
  if (val === 0) muted.value = true;
  else muted.value = false;
});

watch(muted, (m) => {
  if (m) audio.volume = 0;
  else audio.volume = Math.max(0.01, Number(volume.value) || 0.5);
});

// 让歌词容器保持当前句居中
async function recenterLyrics({ instant = false } = {}) {
  await nextTick();
  const box = lyricsBox.value;
  const innerEl = inner.value;
  if (!box || !innerEl) return;
  const els = innerEl.children;
  const idx = currentIndex.value;
  if (!els || !els[idx]) return;
  const target = els[idx];
  // 目标元素相对于 inner 的距离
  const elCenter = target.offsetTop + target.offsetHeight / 2;
  const boxCenter = box.clientHeight / 2;
  const offset = boxCenter - elCenter;
  if (instant) {
    // 临时禁用过渡以避免从顶部跳动
    innerEl.style.transition = "none";
    translateY.value = offset;
    // 强制重绘后恢复过渡
    void innerEl.offsetHeight;
    innerEl.style.transition = "";
  } else {
    translateY.value = offset;
  }
}

watch(currentIndex, () => {
  recenterLyrics();
});

// watch currentTime from range input (seeking)
watch(currentTime, (v, old) => {
  if (Math.abs((audio.currentTime || 0) - v) > 0.2) {
    // user likely dragged; don't overwrite until next timeupdate
    audio.currentTime = v;
  }
});

onMounted(async () => {
  // 初始化时根据屏幕宽度设置字体大小
  setSizesFromWidth(screenWidth.value);

  // 添加窗口大小变化监听器
  window.addEventListener("resize", () => {
    screenWidth.value = window.innerWidth;
    setSizesFromWidth(screenWidth.value);
  });

  await loadLrc();
  // 初始置中（无动画）
  await nextTick();
  recenterLyrics({ instant: true });
});
</script>

<style>
/* 全局样式，避免页面滚动并填充全屏背景 */
html,
body,
#app {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
}
.app {
  position: relative;
  width: 100%;
  height: 100vh;
  font-family: "TZXK", system-ui, -apple-system, "Segoe UI", Roboto,
    "Helvetica Neue", Arial;
  color: white;
}

/* 背景图 */
.app {
  background-image: url("./assets/imgs/bg.jpg");
  background-size: cover;
  background-position: center;
}

/* 半透明叠层，弱化背景便于阅读 */
.overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
}

.container {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  height: 100%;
}

.lyrics-box {
  flex: 0 0 50%;
  position: relative;
  overflow: hidden; /* 不显示滚动条 */
  display: flex;
  align-items: flex-start; /* 使用 flex-start，使用 translateY 控制垂直居中 */
}

.lyrics-inner {
  width: 100%;
  transition: transform 350ms ease;
  will-change: transform;
  /* 为了测量定位，使用绝对定位内联块 */
  padding: 200px 30px;
}

.lyric-line {
  position: relative;
  height: var(--other-line-height, 56px);
  line-height: var(--other-line-height, 56px);
  font-size: var(--other-size, 32px);
  text-align: center;
  margin: 6px 0;
}

.lyric-line .bg-text {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: 0;
  width: 100%;
  color: rgba(255, 255, 255, 0.5);
  z-index: 1;
  font-size: var(--other-size, 32px);
}

.lyric-line .fg-text {
  position: relative;
  z-index: 2;
  color: rgba(255, 255, 255, 0.5);
  font-size: var(--other-size, 32px);
}

.lyric-line.current {
  height: var(--current-line-height, 120px);
  line-height: var(--current-line-height, 120px);
}

.lyric-line.current .bg-text {
  color: rgba(255, 255, 255, 0.8);
  font-size: var(--bg-size, 84px);
  filter: none;
  -webkit-text-stroke: 0px rgba(255, 255, 255, 0.5);
}

.lyric-line.current .fg-text {
  color: red;
  font-size: var(--fg-size, 36px);
  position: relative;
  z-index: 3;
}

/* 控制区 */
.controller-box {
  flex: 1 1 30%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 16px 24px;
  box-sizing: border-box;
}

/* 控制区默认隐藏：透明且不可交互。使用 visible 类控制显示 */
.controller-box {
  opacity: 0;
  transition: opacity 300ms ease;
}
.controller-box.visible {
  opacity: 1;
}

.controls {
  display: flex;
  align-items: center;
  gap: 16px;
}

.volume-wrap {
  display: flex;
  align-items: center;
  gap: 8px;
}

.volume {
  width: 120px;
}

.mute-btn {
  padding: 6px 10px;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.06);
  color: white;
  border: 1px solid rgba(255, 255, 255, 0.08);
}

.play-btn {
  padding: 8px 16px;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.1);
  color: white;
  border: 1px solid rgba(255, 255, 255, 0.12);
}

.time {
  font-size: 14px;
}

.progress {
  width: 100%;
  margin-top: 12px;
}

/* 字体加载（项目内的 ttf） */
@font-face {
  font-family: "TZXK";
  src: url("./assets/fonts/演示镇魂行楷.ttf") format("truetype");
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}
</style>
